//============================================================================================
/**
 * @file	field_amaikaori.c
 * @brief	フィールド技：甘い香り
 * @author	Nozomu Saito
 * @date	2006.06.01
 */
//============================================================================================
#include "common.h"
#include "fieldsys.h"
#include "player.h"
#include "field_cutin.h"

#include "amaikaori_eff.h"

#include "field_skill_prm.h"

#include "field_amaikaori.h"

#include "hiden_effect.naix"

#include "pair_poke.h"

#define PPA_ANM_NUM	(3)

typedef struct AMAIKAORI_WORK_tag
{
	TCB_PTR TcbCutIn;
	EVENT_AMAIKAORI_EFF_WORK *EffWork;
	int PokePos;
}AMAIKAORI_WORK;

//連れポケエフェクト用ワーク
typedef struct PP_AMAIKAORI_WORK_tag
{
	NNSFndAllocator Allocator;

	FLD_3DOBJ_MDL	Mdl;
	FLD_3DOBJ_ANM	Anm[PPA_ANM_NUM];
	FLD_3DOBJ		Obj;
}PP_AMAIKAORI_WORK;

static void PairPokeAmaikaoriEvtCall(FIELDSYS_WORK *fsys);
static BOOL PairPokeAmaikaoriEvt(GMEVENT_CONTROL * event);
static void InitGraphicData(const int inHeapID, FIELDSYS_WORK *fsys, PP_AMAIKAORI_WORK *outWork);
static void DelGraphicData(PP_AMAIKAORI_WORK *outWork);
static BOOL AnimeNoLoop(FLD_3DOBJ_ANM *anm, const u8 inNum);
static void SetAnmFrame(FLD_3DOBJ_ANM *anm, const u8 inNum, const u32 inFrame);

//==============================================================================
/**
 * あまいかおりイベント
 *
 * @param	event		イベントぽピンタ
 *
 * @retval  BOOL		TRUE：イベント終了	FALSE：イベント継続
 */
//==============================================================================
BOOL GMEVENT_Amakikaori( GMEVENT_CONTROL *event )
{
	FIELDSYS_WORK *fsys = FieldEvent_GetFieldSysWork( event );
	FLD_SKILL_PRM *work = FieldEvent_GetSpecialWork( event );
	int *seq = FieldEvent_GetSeqWork(event);
	AMAIKAORI_WORK *skill_work = work->Work;

	switch(*seq){
	case 0:
		{
			int pos;
			//ポケ位置を退避
			pos = *((int*)work->Work);
			//次のワーク確保のために解放
			sys_FreeMemoryEz(work->Work);

			//スキル固有メモリ確保
			work->Work = sys_AllocMemoryLo( HEAPID_WORLD, sizeof(AMAIKAORI_WORK) );
			{
				AMAIKAORI_WORK *aw = work->Work;
				aw->PokePos = pos;
			}
		}
		(*seq)++;
		break;
	case 1:
		//甘い香りエフェクトイベント内で解放してくれるので、確保だけ
		{
			int size = FLDMAP_Amaikaori_WorkSize();
			skill_work->EffWork = sys_AllocMemoryLo( HEAPID_WORLD, size );
			memset( skill_work->EffWork, 0, size );
		}

		{
			//自機の形態を取得
			int player_form = Player_FormGet( fsys->player );
			if ((player_form == HERO_FORM_SWIM)||(player_form == HERO_FORM_CYCLE)){
				(*seq)++;
			}else{
				//連れ歩きが表示状態で、連れ歩きポケが使用したかで分岐
				if ( (skill_work->PokePos == PairPoke_GetPokeListNo(fsys))&&
						(PairPoke_IsVisible(fsys)) ){
					//連れ歩きアニメ待ちイベントコール
					FieldEvent_Call(event, PairPokeEvAnm_WaitAnmEvent, NULL);
					(*seq)=4;
				}else{
					(*seq)++;
				}
			}
		}
		break;
	case 2:		//カットイン
		{
			int sex = Player_SexGet( fsys->player );
			skill_work->TcbCutIn = FieldCutIn_Init( fsys, CUTIN_TYPE_HIDEN, work->PokeParam, sex );
		}
		(*seq)++;
		break;
	case 3:		//カットイン待ち
		if( FieldCutIn_EndCheck(skill_work->TcbCutIn) ){
			FieldCutIn_End( skill_work->TcbCutIn );	//カットイン終了
			(*seq) = 6;
		}
		break;
	case 4:		//連れ歩きポケ挙動
		{
			u8 jump_num;
			//使用したポケのタイプが草タイプかどうかで分岐
			if( PairReact_IsSameType(fsys, KUSA_TYPE) ){
				//ジャンプ2回
				jump_num = 2;
				//機嫌値+1
				PAIR_POKE_HUMOR_AddVal(fsys->PairPokeHumor, 1);
			}else{
				//ジャンプ1回
				jump_num = 1;
			}
			//ジャンプ
			PairReact_JumpAct(fsys, jump_num);
			(*seq)++;
		}
		break;
	case 5:
		//連れポケの甘い香り散布
		OS_Printf("散布！\n");
		PairPokeAmaikaoriEvtCall(fsys);
		(*seq)++;
		break;
	case 6:		//エフェクトコール
		FieldEvent_Call(event, FLDMAP_AmaikaoriEvent, skill_work->EffWork);
		(*seq)++;
		break;
	case 7:		//ワーク解放
		sys_FreeMemoryEz(work->Work);
		sys_FreeMemoryEz(work);
		return TRUE;
	}

	return FALSE;
}

//==============================================================================
/**
 * 連れ歩きポケ甘い香りエフェクトイベントコール
 *
 * @param	fsys			フィールドシステムポインタ
 *
 * @retval  none
 */
//==============================================================================
static void PairPokeAmaikaoriEvtCall(FIELDSYS_WORK *fsys)
{
	PP_AMAIKAORI_WORK *paw;
	paw = sys_AllocMemoryLo(HEAPID_FIELD, sizeof(PP_AMAIKAORI_WORK));

	//初期化
	InitGraphicData( HEAPID_FIELD, fsys, paw );
	//イベントコール
	FieldEvent_Call(fsys->event, PairPokeAmaikaoriEvt, paw);
}

//==============================================================================
/**
 * 連れ歩きポケ甘い香りエフェクトイベント
 *
 * @param	event		イベントポインタ
 *
 * @retval  BOOL		TRUE：イベント終了	FALSE：イベント継続
 */
//==============================================================================
static BOOL PairPokeAmaikaoriEvt(GMEVENT_CONTROL * event)
{
	PP_AMAIKAORI_WORK * paw = FieldEvent_GetSpecialWork(event);
	int *seq = FieldEvent_GetSeqWork(event);
	switch(*seq){
	case 0:		//アニメ終了監視
		if ( AnimeNoLoop( paw->Anm, PPA_ANM_NUM ) ){
			(*seq)++;
		}
		//描画
		FLD_3DObjDraw( &paw->Obj );
		break;
	case 1:		//終了
		DelGraphicData(paw);
		sys_FreeMemoryEz(paw);
		return TRUE;
	}
	return FALSE;
}

//==============================================================================
/**
 * グラフィックデータ初期化
 *
 * @param	inHeapID		ヒープID
 * @param	fsys			フィールドシステムポインタ
 * @param	outWork			ワークポインタ
 *
 * @retval  none
 */
//==============================================================================
static void InitGraphicData(const int inHeapID, FIELDSYS_WORK *fsys, PP_AMAIKAORI_WORK *outWork)
{
	// アロケーター作成
	sys_InitAllocator( &outWork->Allocator, inHeapID, 32 );

	//モデルロード
	FLD_3DObjMdlLoad(&outWork->Mdl, ARC_HIDEN_EFFECT , NARC_hiden_effect_e_kaori_nsbmd, inHeapID);

	//アニメデータロード
	FLD_3DObjAnmLoad(&outWork->Anm[0], &outWork->Mdl, ARC_HIDEN_EFFECT, NARC_hiden_effect_e_kaori_nsbma,
		inHeapID, &outWork->Allocator );
	FLD_3DObjAnmLoad(&outWork->Anm[1], &outWork->Mdl, ARC_HIDEN_EFFECT, NARC_hiden_effect_e_kaori_nsbtp,
		inHeapID, &outWork->Allocator );
	FLD_3DObjAnmLoad(&outWork->Anm[2], &outWork->Mdl, ARC_HIDEN_EFFECT, NARC_hiden_effect_e_kaori_nsbca,
		inHeapID, &outWork->Allocator );


	//描画オブジェクト初期化
	FLD_3DObjInit( &outWork->Obj, &outWork->Mdl );

	//アニメをリンク
	FLD_3DObjAddAnm( &outWork->Obj, &outWork->Anm[0] );
	FLD_3DObjAddAnm( &outWork->Obj, &outWork->Anm[1] );
	FLD_3DObjAddAnm( &outWork->Obj, &outWork->Anm[2] );

	//フレームセット
	SetAnmFrame(outWork->Anm, PPA_ANM_NUM, 0);

	//座標セット
	{
		VecFx32 vec;
		FieldOBJ_VecPosGet( PairPoke_GetFldObjPtr(fsys), &vec );
		FLD_3DObjSetMatrix( &outWork->Obj, vec.x, vec.y, vec.z );
	}

	//描画フラグ設定	(表示)
	FLD_3DObjSetDraw( &outWork->Obj, TRUE );
}

//==============================================================================
/**
 * アニメデータ削除
 *
 * @param	outWork		ワークポインタ
 *
 * @retval 	none
 */
//==============================================================================
static void DelGraphicData(PP_AMAIKAORI_WORK *outWork)
{
	//アニメデータ破棄
	FLD_3DObjAnmDelete( &outWork->Anm[2], &outWork->Allocator);
	FLD_3DObjAnmDelete( &outWork->Anm[1], &outWork->Allocator);
	FLD_3DObjAnmDelete( &outWork->Anm[0], &outWork->Allocator);
	//モデルデータ破棄
	FLD_3DObjMdlDelete( &outWork->Mdl);
}

//==============================================================================
/**
 * アニメフレーム更新関数
 *
 * @param	anm			アニメポインタ配列
 * @param	inNum		アニメ数
 *
 * @retval  BOOL		TRUE：アニメ終了	FALSE：アニメ継続
 */
//==============================================================================
static BOOL AnimeNoLoop(FLD_3DOBJ_ANM *anm, const u8 inNum)
{
	u8 i;
	BOOL end;
	u8 end_num = 0;
	for (i=0;i<inNum;i++){
		end = FLD_3DObjAnmNoLoop( &anm[i], FX32_ONE );
		if (end){
			OS_Printf("%d:アニメ終了\n",i);
			end_num++;
		}
	}
	if (end_num == inNum){
		return TRUE;
	}

	return FALSE;
}

//==============================================================================
/**
 * アニメフレームセット
 *
 * @param	anm			アニメポインタ配列
 * @param	inNum		アニメ数
 * @param	inFrame		フレーム
 *
 * @retval  none
 */
//==============================================================================
static void SetAnmFrame(FLD_3DOBJ_ANM *anm, const u8 inNum, const u32 inFrame)
{
	u8 i;
	for (i=0;i<inNum;i++){
		FLD_3DObjAnmSet( &anm[i], inFrame  );
	}
}
